/*------------------------------

	Space Is The Place v 0.1
		by Sestze

------------------------------*/

SITP = {}

include( 'shared.lua' )
include( 'asteroids.lua' ) -- makes asteroids
include( 'spawnpoints.lua' ) -- sets spawnpoints for gm_new_worlds and gm_twinsuns_fixed
include( 'teams.lua' ) -- makes teamjoin concmds
include( 'economy.lua' ) -- sets up money
include( 'costs.lua' ) -- sets up costs
include( 'restrictions.lua' ) -- restricts sents/sweps
AddCSLuaFile( "teams.lua" ) 
AddCSLuaFile( "cl_init.lua" )
AddCSLuaFile( "shared.lua" )
AddCSLuaFile( "cl_menu.lua" ) -- clientside menu for team selection and help
AddCSLuaFile( "cl_economy.lua" ) -- clientside economy and team hud paint

ISSITP = true

local sitp_ready = 0
SetGlobalInt("sitp_ready", 0)

local NextUpdateTime = 0

local AsteroidUpdate = 0

function GM:Think()
	if(sitp_ready == 1) then
		if(NextUpdateTime <  CurTime()) then
			self:SITP_SpaceAffectPlayers()
			self:SITP_SpaceAffectEnts()
			NextUpdateTime = CurTime() + 0.5
		end
		
		if(AsteroidUpdate < CurTime()) then
			local maxasteroids = GetConVar( "sitp_maxasteroids" ):GetInt()
			local waveamount = GetConVar( "sitp_asteroidwave" ):GetInt()
			
			local Amount = math.min(maxasteroids - SITP_TotalAsteroids, waveamount)
			
			self:SITP_MakeAsteroids( Amount )
			AsteroidUpdate = CurTime() + 15
		end
	end
end

function GM:SITP_CanSeeGround( ent )
	local chk = false
	
	local trace = {}
	local pos = ent:GetPos()
	trace.start = pos
	trace.endpos = pos - Vector(0,0,512)
	trace.filter = { ent }
	local tr = util.TraceLine( trace )
	if (tr.Hit) then
		if (tr.Entity.sitp_core == true) then
			chk = true
		else
			chk = false
		end
	else
		chk = false
	end
	
	return chk
end

function GM:SITP_IsInPlanet(pos)
	local pchk = "space"
	if not (pos) then return pchk end
	if not (sitp_ready) then return "all"	end
	for _, planet in pairs(self.planets) do
		local Disp = planet.pos - pos
		local len = math.sqrt((Disp.x)*(Disp.x) + (Disp.y)*(Disp.y) + (Disp.z)*(Disp.z))
		if (len < planet.radius) then
			pchk = planet.homeworld
		end
	end
	
	return pchk
end

function GM:SITP_SpaceAffectPlayers()
	for _, ply in pairs(player:GetAll()) do
		local str = self:SITP_IsInPlanet(ply:GetPos())
		if (str == "space") then
			local vchk = false
			if(ply:InVehicle()) then
				local vehicle = ply:GetVehicle()
				if (!vehicle.sitp_core) then
					vehicle.sitp_core = false -- FLAG: Set to FALSE for when CORE is OPERATIONAL
				end
				vchk = vehicle.sitp_core
			elseif(self:SITP_CanSeeGround(ply)) then
				vchk = true
			end
			
			if(vchk == false) then
				if not ply:IsAdmin() then
					if(!ply:InVehicle()) then
						if ply:GetMoveType() == MOVETYPE_NOCLIP then
							ply:SetMoveType(MOVETYPE_WALK)
						end
					end
				end
				ply:TakeDamage( 10 , _ ) -- kill them slowly
				self:SITP_Space(ply)
			else
				local clamp = math.Clamp(ply:Health() + 10, 0, 100)
				ply:SetHealth(clamp)
				self:SITP_UnSpace(ply)
			end
		else
			local clamp = math.Clamp(ply:Health() + 10, 0, 100)
			ply:SetHealth(clamp)
			self:SITP_UnSpace(ply)
		end
		ply.sitp_spacetype = str
		ply:SetNetworkedString("sitp_spacetype", str)
	end
end

function GM:SITP_SpaceAffectEnts()
	for _, class in pairs( self.affected ) do
		local allents = ents.FindByClass( class )
		for _, ent in pairs ( allents ) do
			if(!ent:IsPlayer()) then
				local str = self:SITP_IsInPlanet(ent:GetPos())
				if (str == "space") then
					self:SITP_Space(ent)
				else
					self:SITP_UnSpace(ent)
				end
				ent.sitp_spacetype = str
			end
		end
	end
end

function GM:SITP_Space(ent)
	if(not (ent and ent:IsValid())) then return end
	if(ent.sitp_inspace == nil) then
		ent.sitp_inspace = false
		ent.sitp_defaultgravity = true
		ent.sitp_defaultdrag = true
		local phys = ent:GetPhysicsObject()
		if(phys:IsValid() and ent:GetClass() != "sitp_asteroid" and ent:GetClass() != "debris") then
			ent.sitp_defaultgravity = phys:IsGravityEnabled()
			ent.sitp_defaultdrag = phys:IsDragEnabled()
		end
	end
	
	if(ent.sitp_inspace != true) then
		if(!ent.sitp_hasenteredspace) then
			SITP_ApplyCost( ent )
			ent.sitp_hasenteredspace = true
		end
		ent.sitp_inspace = true
		if(ent:IsPlayer()) then
			ent:SetGravity(0.00001)
		else
			local phys = ent:GetPhysicsObject()
			if(phys:IsValid()) then
				phys:EnableGravity( false )
				phys:EnableDrag ( false )
			end
			ent:SetGravity(0.00001)
		end
	end
end

function GM:SITP_UnSpace(ent)
	if(not (ent and ent:IsValid())) then return end
	if(ent.sitp_inspace == nil) then
		ent.sitp_inspace = true
		ent.sitp_defaultgravity = true
		ent.sitp_defaultdrag = true
		local phys = ent:GetPhysicsObject()
		if(phys:IsValid() and ent:GetClass() != "sitp_asteroid" and ent:GetClass() != "debris") then
			ent.sitp_defaultgravity = phys:IsGravityEnabled()
			ent.sitp_defaultdrag = phys:IsDragEnabled()
		end
	end
	
	if(ent.sitp_inspace != false) then
		if(!ent.sitp_hasenteredspace) then
			if(ent.sitp_spacetype == "planet") then
				SITP_ApplyCost( ent )
				ent.sitp_hasenteredspace = true
			end
		end
		ent.sitp_inspace = false
		if( ent:IsPlayer() ) then
			ent:SetGravity(1)
		else
			local phys = ent:GetPhysicsObject()
			if(phys:IsValid()) then
				phys:EnableGravity( ent.sitp_defaultgravity )
				phys:EnableDrag ( ent.sitp_defaultdrag )
			end
			ent:SetGravity(1)
		end
	end
end

-- Inits

function GM:InitPostEntity()
	self:SITP_GetAffected()
	self:SITP_GetPlanets()
	timer.Simple(5, function() 
		RunConsoleCommand("acf_healthmod", "1")
		RunConsoleCommand("acf_armormod", "2")
		RunConsoleCommand("acf_ammomod", "5")
		ACF.AmmoMod = 5
		ACF.ArmorMod = 2
		ACF.Threshold = 150
		sitp_ready = 1
		end )
end

function GM:SITP_GetAffected()
	local SENTList = scripted_ents.GetList()
	for _, item in pairs (SENTList) do
		local name = item.t.Classname
		local found = 0
		for _, check in pairs( self.affected ) do
			if ( check == name ) then
				found = 1
				break
			end
		end
		if( found == 0 ) then table.insert(self.affected, name) end
	end
end

function GM:SITP_GetPlanets()
	local  allcases = ents.FindByClass("logic_case")
	for _, ent in pairs (allcases) do
		local planettable = ent:GetKeyValues()
		for key, value in pairs ( planettable ) do
			if key == "Case01" then
				if value == "planet" or value == "planet2" then
					local temptable = {}
					local radius = 0
					for key2, value2 in pairs( planettable ) do
						if(key2 == "Case02") then radius = tonumber(value2) end
					end
					temptable.num = num
					temptable.radius = radius
					temptable.pos = ent:GetPos()
					
					temptable.homeworld = self:SITP_IsHomeworld(ent:GetPos(), radius)
					
					table.insert (self.planets, temptable)
					--print("I found a Planet! ID: " .. tostring(ent:EntIndex()))
				end
			end
		end
	end
end

function GM:CheckAffected (ply, ent)
	if not (ent and ent:IsValid()) then return end
	local c = ent:GetClass()
	if table.HasValue(self.affected, c) then return end
	table.insert(self.affected, c)
end

function GM:SITP_IsHomeworld ( pos, radius )
	local vchk = "planet"
	
	if table.HasValue(SITP.MapList, game.GetMap()) then
		local FSA = SITP.SpawnPoints[game.GetMap()]["FSA"]
		local GMC = SITP.SpawnPoints[game.GetMap()]["GMC"]
		
		for i = 1, 5 do
			local Disp = FSA[i] - pos
			local Len = math.sqrt(Disp.x * Disp.x + Disp.y * Disp.y + Disp.z * Disp.z)
			if(Len < radius) then
				vchk = "fsa"
				--print("Found a homeworld!")
			end
		end
		
		for i = 1, 5 do
			local Disp = GMC[i] - pos
			local Len = math.sqrt(Disp.x * Disp.x + Disp.y * Disp.y + Disp.z * Disp.z)
			if(Len < radius) then
				vchk = "gmc"
				--print("Found a homeworld!")
			end
		end
		
		local spawns = ents.FindByClass("info_player_deathmatch")
		
		for _, ent in pairs(spawns) do
			local Disp = ent:GetPos() - pos
			local Len = math.sqrt(Disp.x * Disp.x + Disp.y * Disp.y + Disp.z * Disp.z)
			if(Len < radius) then
				vchk = "merc"
				--print("Found a homeworld!")
			end
		end
		local spawns = ents.FindByClass("info_player_start")
		for _, ent in pairs(spawns) do
			local Disp = ent:GetPos() - pos
			local Len = math.sqrt(Disp.x * Disp.x + Disp.y * Disp.y + Disp.z * Disp.z)
			if(Len < radius) then
				vchk = "merc"
				--print("Found a homeworld!")
			end
		end
	else
		local spawns = ents.FindByClass("info_player_deathmatch")
		
		for _, ent in pairs(spawns) do
			local Disp = ent:GetPos() - pos
			local Len = math.sqrt(Disp.x * Disp.x + Disp.y * Disp.y + Disp.z * Disp.z)
			if(Len < radius) then
				vchk = "all"
				--print("Found a homeworld!")
			end
		end
		local spawns = ents.FindByClass("info_player_start")
		for _, ent in pairs(spawns) do
			local Disp = ent:GetPos() - pos
			local Len = math.sqrt(Disp.x * Disp.x + Disp.y * Disp.y + Disp.z * Disp.z)
			if(Len < radius) then
				vchk = "all"
				--print("Found a homeworld!")
			end
		end
	end
	return vchk
end

hook.Add( "PlayerSpawnedSENT", "Check Affected", GM.CheckAffected)

-- Menu junk

function GM:ShowHelp( ply )
	umsg.Start( "SITPHelp", ply )
	umsg.End()
end
